package com.dxtx.util;

import android.annotation.SuppressLint;
import android.os.AsyncTask;
import android.os.Build;
import android.util.Log;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * * An executor for concurrently executing AsyncTask tasks It takes all work
 * for understanding device`s Android version and executes your AsyncTasks tasks
 * concurrently
 */
public class AsyncTaskExecutor {
	private static final String TAG = "AsyncTaskExecutor";

	private static final int CORE_POOL_SIZE;

	private static final int MAXIMUM_POOL_SIZE;
	// 当线程池中的线程数量大于
	// corePoolSize时，如果某线程空闲时间超过keepAliveTime，线程将被终止�?�这样，线程池可以动态的调整池中的线程数�?
	private static final int KEEP_ALIVE;

	private static final TimeUnit TIME_UNIT;

	private static final BlockingQueue<Runnable> concurrentPoolWorkQueue;

	private static final ThreadFactory concurrentThreadFactory;

	private static ThreadPoolExecutor concurrentExecutor;

	private AsyncTaskExecutor() {
	}

	static {
		CORE_POOL_SIZE = 10;
		MAXIMUM_POOL_SIZE = 128;
		KEEP_ALIVE = 5;
		TIME_UNIT = TimeUnit.SECONDS;
		concurrentPoolWorkQueue = new LinkedBlockingQueue<Runnable>(CORE_POOL_SIZE * 2);
		concurrentThreadFactory = new AsyncTaskThreadFactory();
	}

	public static synchronized ThreadPoolExecutor getExecutor() {
		if (concurrentExecutor == null) {
			concurrentExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TIME_UNIT,
					concurrentPoolWorkQueue, concurrentThreadFactory);
			concurrentExecutor.setKeepAliveTime(KEEP_ALIVE * 2, TimeUnit.SECONDS);
			concurrentExecutor.allowCoreThreadTimeOut(true);
		}
		Log.e(TAG,
				"ActiveCount:" + concurrentExecutor.getActiveCount() + ",CompletedTaskCount:"
						+ concurrentExecutor.getCompletedTaskCount() + ",CorePoolSize:"
						+ concurrentExecutor.getCorePoolSize() + ",PoolSize:" + concurrentExecutor.getPoolSize()
						+ ",LargestPoolSize:" + concurrentExecutor.getLargestPoolSize() + ",TaskCount:"
						+ concurrentExecutor.getTaskCount());
		return concurrentExecutor;
	}

	public static void shutdown() {
		if (concurrentExecutor != null) {
			concurrentExecutor.shutdownNow();
			concurrentExecutor = null;
		}
	}

	/**
	 * * Concurrently executes AsyncTask on any Android version * @param task to
	 * execute * @param params for task * @return executing AsyncTask
	 */
	@SuppressLint("NewApi")
	public static <Params, Progress, Result> AsyncTask<Params, Progress, Result> executeConcurrently(
			AsyncTask<Params, Progress, Result> task, Params... params) {
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
			if (null != concurrentExecutor) {
				task.executeOnExecutor(concurrentExecutor, params);
			}
		} else {
			task.executeOnExecutor(AsyncTaskExecutor.getExecutor(), params);
		}
		return task;
	}

	/** * Thread factory for AsyncTaskExecutor */
	private static class AsyncTaskThreadFactory implements ThreadFactory {
		private final AtomicInteger count = new AtomicInteger(1);

		@Override
		public Thread newThread(Runnable r) {
			Log.d(TAG, "  AsyncTask #" + count.get());
			return new Thread(r, "AsyncTask #" + count.getAndIncrement());
		}
	}
}